package com.shj.web.security;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.shj.model.SysUserRole;
import com.shj.service.SysUserRoleService;
import com.shj.web.config.JwtConfig;
import com.shj.web.security.entity.SelfUserEntity;
import com.shj.web.util.BeanUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description TODO JWT接口请求校验过滤器
 * @Author songhuajian
 * @Date 2020/3/13 15:50
 **/
public class JwtAuthenticationTokenFilter extends BasicAuthenticationFilter {

    public JwtAuthenticationTokenFilter(AuthenticationManager authenticationManager){ super(authenticationManager);}

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        //获取请求头中JWT的token
        String tokenHeader = request.getHeader(JwtConfig.tokenHeader);
        if (null != tokenHeader && tokenHeader.startsWith(JwtConfig.tokenPrefix)){
            try {
                // 截取JWT前缀
                String token = tokenHeader.replace(JwtConfig.tokenPrefix, "");
                // 解析JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(JwtConfig.secret)
                        .parseClaimsJws(token)
                        .getBody();
                // 获取用户名
                String username = claims.getSubject();
                String userId = claims.getId();

                if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(userId)){
                    List<GrantedAuthority> authorities = new ArrayList<>();
                    // 获取token中的角色
//                    String authority = claims.get("authorities").toString();
//                    if (!StringUtils.isEmpty(authority)){
//                        String replace = authority.replace("=", ":");
//                        Gson gson = new Gson();
//                        List<Map<String, String>> authorityMap = gson.fromJson(replace, List.class);
//                        System.out.println(JSONObject.toJSONString(authorityMap));
//                        for (Map<String, String> role : authorityMap){
//                            if (!StringUtils.isEmpty(role)){
//                                authorities.add(new SimpleGrantedAuthority(role.get("authority")));
//                                System.out.println(role.get("authority"));
//                            }
//                        }
//                    }
                    // 从数据库查找用户角色
                    SysUserRoleService sysUserRoleService = BeanUtil.getBean(SysUserRoleService.class, request);
                    List<SysUserRole> roles = sysUserRoleService.findByUserId(userId);
                    for (SysUserRole role : roles) {
                        String roleId = role.getRoleId();
                        authorities.add(new SimpleGrantedAuthority(roleId));
                    }
                    // 组装参数
                    SelfUserEntity selfUserEntity = new SelfUserEntity();
                    selfUserEntity.setUsername(claims.getSubject());
                    selfUserEntity.setUserId(claims.getId());
                    selfUserEntity.setAuthorities(authorities);
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(selfUserEntity, userId, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (Exception e){
                e.printStackTrace();
            }
        }
        filterChain.doFilter(request, response);
    }
}
